package com.zhuxulin.lottery.net;

import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.net.http.AndroidHttpClient;
import android.util.Log;

import com.zhuxulin.lottery.App;
import com.zhuxulin.lottery.utils.LogUtils;

public class Server {
	private static final String TAG = Server.class.getSimpleName();
	private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

	private static Server instance;

	private Context context;
	private HttpContext httpContext;
	private CookieStore cookieStore;
	private HttpParams httpParams;

	public static Server getInstance(Context context) {
		if (instance == null) {
			instance = new Server(context);
		}
		return instance;
	}

	private Server(Context context) {
		this.context = context;
		httpContext = new BasicHttpContext();
		cookieStore = new BasicCookieStore();
		httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
		HttpConnectionParams.setSoTimeout(httpParams, 10000);
	}

	/**
	 * 重置网络连接，清空Cookie
	 */
	public void reset() {
		cookieStore.clear();
	}

	/**
	 * 执行相应的网络请求
	 * 
	 * @param request
	 *            请求对象
	 * @param iCall
	 *            结果集中dataSet的解释类型，为null时忽略该数据
	 * @return 请求结果
	 */
	public void execute(Request request, ICall call) {
		Response response = null;
		HttpUriRequest req = null;
		String uri = request.getHost() + request.getPath();
		switch (request.getMethod()) {
		case GET:
			req = new HttpGet(uri + request.getQueryString());
			break;
		case POST:
			req = new HttpPost(uri);
			((HttpPost) req).setEntity(request.getEntity());
			break;
		case PUT:
			req = new HttpPut(uri);
			((HttpPut) req).setEntity(request.getEntity());
			break;
		case DELETE:
			req = new HttpDelete(uri + request.getQueryString());
			break;
		}
		req.setParams(httpParams);

		AndroidHttpClient client = AndroidHttpClient.newInstance("android");
		try {
			HttpResponse resp = client.execute(req, httpContext);
			if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				StringBuffer content = new StringBuffer();
				InputStream in = resp.getEntity().getContent();
				byte[] buf = new byte[1024];
				int count = 0;
				while ((count = in.read(buf, 0, buf.length)) > 0) {
					content.append(new String(buf, 0, count, "utf-8"));
				}
				in.close();
				LogUtils.i(TAG, content.toString());
				call.onResult(content.toString(), resp.getStatusLine().getStatusCode());
			} else {
				call.onResult("error", resp.getStatusLine().getStatusCode());
			}
		} catch (IOException e) {
		}
		client.close();
	}

	/**
	 * 执行相应的网络请求
	 * 
	 * @param request
	 *            请求对象
	 * @param iCall
	 *            结果集中dataSet的解释类型，为null时忽略该数据
	 * @return 请求结果
	 */
	public <T> Response<T> execute(Request request, Response<T> dataType) {
		Response<T> response = null;
		HttpUriRequest req = null;
		String uri = request.getHost() + request.getPath();
		switch (request.getMethod()) {
		case GET:
			req = new HttpGet(uri + request.getQueryString());
			break;
		case POST:
			req = new HttpPost(uri);
			((HttpPost) req).setEntity(request.getEntity());
			break;
		case PUT:
			req = new HttpPut(uri);
			((HttpPut) req).setEntity(request.getEntity());
			break;
		case DELETE:
			req = new HttpDelete(uri + request.getQueryString());
			break;
		}
		req.setParams(httpParams);

		AndroidHttpClient client = AndroidHttpClient.newInstance(App.MODEL);
		try {
			HttpResponse resp = client.execute(req, httpContext);
			if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				StringBuffer content = new StringBuffer();
				InputStream in = resp.getEntity().getContent();
				byte[] buf = new byte[1024];
				int count = 0;
				while ((count = in.read(buf, 0, buf.length)) > 0) {
					content.append(new String(buf, 0, count, "utf-8"));
				}
				in.close();
				LogUtils.i(TAG, content.toString());
				// response = parseResponse(content.toString(), dataType);
			} else {
				response = new Response<T>();
				response.code = -resp.getStatusLine().getStatusCode();
				response.message = request.toString();
			}
		} catch (IOException e) {
			response = new Response<T>();
			response.code = Response.CODE_NETWORK_ERROR;
			response.message = e.getMessage();
			return response;
		} catch (IllegalArgumentException e) {
			response = new Response<T>();
			response.code = Response.CODE_SERVER_ADDR_ERROR;
			return response;
		} finally {
			client.close();
		}
		return response;
	}

	private <T> Response<T> parseResponse(String content, Class<T> dataType) {
		Response<T> response = new Response<T>();
		try {
			JSONObject resp = new JSONObject(content);
			response.code = resp.getInt("code");
			response.message = resp.getString("message");
			if (dataType != null) {
				JSONObject result = resp.optJSONObject("result");
				if (result != null) {
					response.totalCount = result.getInt("totalCount");
					response.startIndex = result.getInt("startIndex");
					response.dataCount = result.getInt("dataCount");
					if (response.dataCount > 0) {
						// response.dataList =
						// parseDataList(result.getJSONArray("dataSet"),
						// dataType);
					}
				}
			}
		} catch (JSONException e) {
			Log.e(TAG, "", e);
			response.code = Response.CODE_RESPONSE_ERROR;
			response.message = e.getMessage();
		}
		return response;
	}
}
